vmx: avoid taking locks with irqs disabled
authorKeir Fraser <keir.fraser@citrix.com>
Mon, 20 Oct 2008 14:31:54 +0000 (15:31 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Mon, 20 Oct 2008 14:31:54 +0000 (15:31 +0100)
Shuffle the bits of the vmexit handler that run with EFLAGS.IF == 0 up
to the top.  Otherwise we end up calling spin_lock() with interrupts
disabled, which can deadlock against the time-synchronization
rendezvous code.

Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com>
xen/arch/x86/hvm/vmx/vmx.c

index 407b677899d360cc5ac4cebbab11517991e37899..ed99ec8073ce2d922cfffcfd429084a662ba0222 100644 (file)
@@ -2056,8 +2056,12 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
 
     perfc_incra(vmexits, exit_reason);
 
-    if ( exit_reason != EXIT_REASON_EXTERNAL_INTERRUPT )
-        local_irq_enable();
+    /* Handle the interrupt we missed before allowing any more in. */
+    if ( exit_reason == EXIT_REASON_EXTERNAL_INTERRUPT )
+        vmx_do_extint(regs);
+
+    /* Now enable interrupts so it's safe to take locks. */
+    local_irq_enable();
 
     if ( unlikely(exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) )
         return vmx_failed_vmentry(exit_reason, regs);
@@ -2185,7 +2189,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs)
         break;
     }
     case EXIT_REASON_EXTERNAL_INTERRUPT:
-        vmx_do_extint(regs);
+        /* Already handled above. */
         break;
     case EXIT_REASON_TRIPLE_FAULT:
         hvm_triple_fault();